package com.devilvan.betrice.poetry.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devilvan.betrice.common.BetriceResultCode;
import com.devilvan.betrice.common.BetriceResultVo;
import com.devilvan.betrice.poetry.constant.PoetryConstant;
import com.devilvan.betrice.poetry.dto.PoetryHeaderDto;
import com.devilvan.betrice.poetry.mapper.PoetryDetailMapper;
import com.devilvan.betrice.poetry.mapper.PoetryKeywordMapper;
import com.devilvan.betrice.poetry.po.PoetryDetailPo;
import com.devilvan.betrice.poetry.po.PoetryHeaderPo;
import com.devilvan.betrice.poetry.po.PoetryKeywordPo;
import com.devilvan.betrice.poetry.repository.PoetryDetailRepository;
import com.devilvan.betrice.poetry.repository.PoetryKeywordRepository;
import com.devilvan.betrice.poetry.service.PoetryHeaderService;
import com.devilvan.betrice.poetry.mapper.PoetryHeaderMapper;
import com.devilvan.betrice.poetry.repository.PoetryHeaderRepository;
import com.devilvan.betrice.request.component.JsoupComponent;
import com.devilvan.betrice.util.UEmpty;
import com.devilvan.betrice.util.UCopy;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Evad.Wu
 * @Description 古诗文网-头信息表 业务逻辑类
 * @date 2022-11-29
 */
@Service
public class PoetryHeaderServiceImpl extends ServiceImpl<PoetryHeaderMapper, PoetryHeaderPo> implements PoetryHeaderService {
    @Resource(name = "jsoupComponent")
    private JsoupComponent jsoupComponent;
    @Resource(name = "transactionTemplate")
    private TransactionTemplate transactionTemplate;

    @Resource(name = "poetryHeaderRepository")
    private PoetryHeaderRepository poetryHeaderRepository;
    @Resource(name = "poetryKeywordRepository")
    private PoetryKeywordRepository poetryKeywordRepository;
    @Resource(name = "poetryDetailRepository")
    private PoetryDetailRepository poetryDetailRepository;
    @Resource(name = "poetryKeywordMapper")
    private PoetryKeywordMapper poetryKeywordMapper;
    @Resource(name = "poetryDetailMapper")
    private PoetryDetailMapper poetryDetailMapper;

    @Override
    public BetriceResultVo<PoetryHeaderPo> doPoetryHeaderSpecificCrawler() {
        BetriceResultVo<PoetryHeaderPo> betriceResultVo = new BetriceResultVo<>();
        LambdaQueryWrapper<PoetryKeywordPo> queryWrapper = new QueryWrapper<PoetryKeywordPo>().lambda();
        queryWrapper.select(PoetryKeywordPo::getKeyword, PoetryKeywordPo::getKeywordUrl);
        queryWrapper.in(PoetryKeywordPo::getKeyword, "诗经", "乐府", "楚辞");
        List<PoetryKeywordPo> poetryKeywordPoList = poetryKeywordMapper.selectList(queryWrapper);
        List<PoetryHeaderPo> poetryHeaderPoList = new ArrayList<>();
        try {
            for (PoetryKeywordPo poetryKeywordPo : poetryKeywordPoList) {
                if ("楚辞".equals(poetryKeywordPo.getKeyword())) {
                    List<PoetryHeaderPo> chuci = this.doChuci(poetryKeywordPo);
                    poetryHeaderPoList.addAll(chuci);
                } else if ("诗经".equals(poetryKeywordPo.getKeyword()) || "乐府".equals(poetryKeywordPo.getKeyword())) {
                    List<PoetryHeaderPo> shijingYuefu = this.doShijingYuefu(poetryKeywordPo);
                    poetryHeaderPoList.addAll(shijingYuefu);
                }
            }
            if (UEmpty.isNotEmpty(poetryHeaderPoList)) {
                poetryHeaderRepository.saveAll(poetryHeaderPoList);
            }
            // 修改poetry_keyword的isCrawl字段为1
            for (PoetryKeywordPo poetryKeywordPo : poetryKeywordPoList) {
                poetryKeywordPo.setIsCrawl(true);
            }
            poetryKeywordRepository.saveAll(poetryKeywordPoList);
            betriceResultVo.result(BetriceResultCode.SUCCESS_200, "操作成功！");
        } catch (Exception e) {
            e.printStackTrace();
            betriceResultVo.result(BetriceResultCode.FAILED_500, "操作失败！");
        }
        return null;
    }

    @Override
    public BetriceResultVo<PoetryHeaderPo> doPoetryHeaderCrawler(String keyword) {
        BetriceResultVo<PoetryHeaderPo> betriceResultVo = new BetriceResultVo<>();
        // 如果指定了关键字就根据关键字采集，否则就获取没有被采集的keyword进行采集
        PoetryKeywordPo poetryKeywordPo = poetryKeywordMapper.findOneByKeywordTitle(keyword);
        Map<String, String> headers = new HashMap<>(1);
        String keywordUrl = poetryKeywordPo.getKeywordUrl();
        headers.put("referer", keywordUrl);
        List<PoetryDetailPo> poetryDetailPoList = new ArrayList<>();
        List<PoetryHeaderPo> poetryHeaderPoList = new ArrayList<>();
        while (true) {
            Element body = jsoupComponent.getBody(keywordUrl, headers);
            Elements contentList = body.select("div#leftZhankai>div.sons>div.cont");
            for (Element content : contentList) {
                // 获取标题
                Elements titleElem = content.select("p:nth-child(2)>a");
                String title = titleElem.text();
                // 获取作者、朝代
                String authorDynasty = content.select("p.source").text();
                String[] split = authorDynasty.split("〔");
                String author = null;
                String dynasty = null;
                if (split.length == 1) {
                    author = split[0];
                } else if (split.length == 2) {
                    author = split[0];
                    dynasty = split[1].replace("〕", "");
                }
                String detailUrl = PoetryConstant.GUSHIWEN_DEFAULT_URL + titleElem.attr("href");
                PoetryHeaderPo poetryHeaderPo = new PoetryHeaderPo();
                poetryHeaderPo.setKeyword(poetryKeywordPo.getKeyword());
                poetryHeaderPo.setTitle(title);
                poetryHeaderPo.setAuthor(author);
                poetryHeaderPo.setDynasty(dynasty);
                poetryHeaderPo.setDetailUrl(detailUrl);
                poetryHeaderPoList.add(poetryHeaderPo);
                Integer isExsist = poetryDetailMapper.findExsistByTitleAndAuthor(title, author);
                if (isExsist != 0) {
                    continue;
                }
                // 获取内容
                Elements htmlText = content.select("div.contson");
                String text = htmlText.text();
                String contentMd = htmlText.html();
                PoetryDetailPo poetryDetailPo = new PoetryDetailPo();
                poetryDetailPo.setTitle(title);
                poetryDetailPo.setAuthor(author);
                poetryDetailPo.setContent(text);
                poetryDetailPo.setContentMd(contentMd);
                poetryDetailPoList.add(poetryDetailPo);
            }
            poetryKeywordPo.setIsCrawl(true);
            // 下一页，若无则跳出循环
            String href = body.select("div#leftZhankai>form#FromPage>div.pagesright>a.amore").attr("href");
            if (UEmpty.isEmpty(href)) {
                break;
            }
            keywordUrl = PoetryConstant.GUSHIWEN_DEFAULT_URL + href;
            String currentPageReferer = headers.get("referer");
            headers.put("referer", currentPageReferer);
        }
        transactionTemplate.execute(status -> {
            poetryKeywordRepository.save(poetryKeywordPo);
            poetryHeaderRepository.saveAll(poetryHeaderPoList);
            poetryDetailRepository.saveAll(poetryDetailPoList);
            return null;
        });
        betriceResultVo.result(BetriceResultCode.SUCCESS_200, "操作成功！");
        return betriceResultVo;
    }

    /**
     * 《诗经》、《乐府》的作品有副标题
     *
     * @param poetryKeywordPo 古诗文关键字对象
     * @return 采集的《诗经》、《乐府》中的作品对象集合
     */
    private List<PoetryHeaderPo> doShijingYuefu(PoetryKeywordPo poetryKeywordPo) {
        final String shijing = "诗经";
        final String yuefu = "乐府";
        List<PoetryHeaderPo> poetryHeaderPoList = new ArrayList<>();
        Map<String, String> headers = new HashMap<>(1);
        // 诗经
        if (shijing.equals(poetryKeywordPo.getKeyword())) {
            headers.put("referer", PoetryConstant.GUSHIWEN_DEFAULT_URL + "/shiwens/default.aspx?tstr=%e8%af%97%e7%bb%8f");
        } else if (yuefu.equals(poetryKeywordPo.getKeyword())) {
            headers.put("referer", PoetryConstant.GUSHIWEN_DEFAULT_URL + "/shiwens/default.aspx?tstr=%e4%b9%90%e5%ba%9c");
        } else {
            return poetryHeaderPoList;
        }
        Element body = jsoupComponent.getBody(poetryKeywordPo.getKeywordUrl(), headers);
        Elements typeContentList = body.select("div.typecont");
        for (Element typeContent : typeContentList) {
            // 主标题
            String title = typeContent.select("div.bookMl>strong").text();
            // 作品
            Elements words = typeContent.select("span>a");
            for (Element word : words) {
                String detailUrl = PoetryConstant.GUSHIWEN_DEFAULT_URL + word.attr("href");
                // 副标题
                String subTitle = word.text();
                PoetryHeaderPo poetryHeaderPo = new PoetryHeaderPo();
                poetryHeaderPo.setKeyword(poetryKeywordPo.getKeyword());
                poetryHeaderPo.setTitle(subTitle);
                poetryHeaderPo.setSubTitle(title);
                poetryHeaderPo.setAuthor(null);
                poetryHeaderPo.setDetailUrl(detailUrl);
                poetryHeaderPoList.add(poetryHeaderPo);
            }
        }
        return poetryHeaderPoList;
    }

    /**
     * 《楚辞》的作品没有副标题
     *
     * @param poetryKeywordPo 古诗文关键字对象
     * @return 采集的《楚辞》中的作品对象集合
     */
    private List<PoetryHeaderPo> doChuci(PoetryKeywordPo poetryKeywordPo) {
        List<PoetryHeaderPo> poetryHeaderPoList = new ArrayList<>();
        Map<String, String> headers = Map.of("referer", "https://so.gushiwen.cn/shiwens/default.aspx?tstr=%e6%a5%9a%e8%be%9e");
        Element body = jsoupComponent.getBody(poetryKeywordPo.getKeywordUrl(), headers);
        Elements spanList = body.select("div.typecont>span");
        for (Element span : spanList) {
            String detailUrl = PoetryConstant.GUSHIWEN_DEFAULT_URL + span.select("a").attr("href");
            String[] titleAuthor = span.text().split("[(]");
            String title = titleAuthor[0];
            String author = titleAuthor[1].replace(")", "");
            PoetryHeaderPo poetryHeaderPo = new PoetryHeaderPo();
            poetryHeaderPo.setKeyword(poetryKeywordPo.getKeyword());
            poetryHeaderPo.setTitle(title);
            poetryHeaderPo.setAuthor(author);
            poetryHeaderPo.setDetailUrl(detailUrl);
            poetryHeaderPoList.add(poetryHeaderPo);
        }
        return poetryHeaderPoList;
    }

    @Override
    public PoetryHeaderPo saveUpdate(PoetryHeaderDto poetryHeaderDto) {
        PoetryHeaderPo poetryHeaderPo = new PoetryHeaderPo();
        UCopy.fullCopy(poetryHeaderDto, poetryHeaderPo);
        return poetryHeaderRepository.saveAndFlush(poetryHeaderPo);
    }

    @Override
    public List<PoetryHeaderPo> saveUpdateBatch(List<PoetryHeaderDto> list) {
        List<PoetryHeaderPo> poetryHeaderPoList = UCopy.fullCopyCollections(list, PoetryHeaderPo.class);
        return poetryHeaderRepository.saveAllAndFlush(poetryHeaderPoList);
    }
}
